/*
 * Copyright 2010 Electronic Business Systems Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package gr.ebs.gssdroid.activities;

import gr.ebs.gssdroid.GssDroid;
import gr.ebs.gssdroid.GssDroidApplication;
import gr.ebs.gssdroid.R;
import gr.ebs.gssdroid.async.GssAsyncTask;
import gr.ebs.gssdroid.async.TaskResult;
import gr.ebs.gssdroid.http.GssHttpCommands;
import gr.ebs.gssdroid.http.GssHttpException;
import gr.ebs.gssdroid.http.SystemErrorException;
import gr.ebs.gssdroid.resource.FileResource;
import gr.ebs.gssdroid.resource.FolderResource;
import gr.ebs.gssdroid.resource.GroupResource;
import gr.ebs.gssdroid.resource.GroupUserResource;
import gr.ebs.gssdroid.resource.GroupsResource;
import gr.ebs.gssdroid.resource.PermissionHolder;
import gr.ebs.gssdroid.resource.RestResource;
import gr.ebs.gssdroid.widget.UserAdapter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;

public class GssProperties extends Activity {
	RestResource res;
	public ProgressDialog myprogress;
	GroupsResource groupsResource;
	String initialTagText="";
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		res = (RestResource) getIntent().getExtras().get("resource");
		if (res instanceof FolderResource) {
			getFolderTask().execute(res.getUri());
		} else {
			getFileTask().execute(res.getUri());
		}
	}

	private void createFolderLayout() {
		((EditText) findViewById(R.id.textFolderName)).setText(((FolderResource) res).getName());
		((TextView) findViewById(R.id.textFolderParent)).setText(((FolderResource) res).getParentName());
		((TextView) findViewById(R.id.textFolderCreation)).setText(GssDroid.formatLocalDateTime(((FolderResource) res).getCreationDate()));
		((TextView) findViewById(R.id.textFolderOwner)).setText(((FolderResource) res).getOwner());
		
		((CheckBox) findViewById(R.id.folderPublic)).setChecked(((FolderResource) res).isReadForAll());
		((CheckBox) findViewById(R.id.folderPublic)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				Log.d("SK", ((FolderResource) res).isReadForAll()+" BEFORE");
				((FolderResource) res).setReadForAll(isChecked);
				Log.d("SK", ((FolderResource) res).isReadForAll()+" AFTER");

			}
		});
		
		((Button) findViewById(R.id.refreshFolder)).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					updateFolder();
					returnToCaller(null);
				} catch (JSONException e) {
					showErrorDialog("JSON ERROR", "A JSON parsing error occured");
				} catch (SystemErrorException e) {
					showErrorDialog("System ERROR", "A system error occured");
					e.printStackTrace();
				} catch (GssHttpException e) {
					if(e.getStatusCode()==409)
						showErrorDialog("Duplicate Folder Name", "A folder with the same name already exists.");
					else if(e.getStatusCode()==405)
						showErrorDialog("No permission", "You dont have permissions to rename this folder.");
					else
						showErrorDialog("Invalid response code", "An invalid response code was returned:"+e.getStatusCode());
				}
			}
		});
		rebuildPermissionList();
		((Button) findViewById(R.id.newPermission)).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if(groupsResource==null){
					getGroupsOnlyTask().execute(getDroidApplication().getUserDetails().getApiPath()+getDroidApplication().getUserDetails().getUsername()+"/groups/");
				}
				else
					showAddDialog();
				
			}
		});
	}

	private void createFileLayout() {
		((EditText) findViewById(R.id.textFolderName)).setText(((FileResource) res).getName());
		((TextView) findViewById(R.id.textFolderParent)).setText(((FileResource) res).getFolderName());
		((TextView) findViewById(R.id.textFolderCreation)).setText(GssDroid.formatLocalDateTime(((FileResource) res).getCreationDate()));
		((TextView) findViewById(R.id.textFolderOwner)).setText(((FileResource) res).getOwner());
		LayoutInflater layoutInflater = LayoutInflater.from(GssProperties.this);
		((CheckBox) findViewById(R.id.folderPublic)).setChecked(((FileResource) res).isReadForAll());
		((CheckBox) findViewById(R.id.folderPublic)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				((FileResource) res).setReadForAll(isChecked);

			}
		});
		((EditText) findViewById(R.id.textTags)).setText(((FileResource) res).getTagsAsString());
	     initialTagText=((FileResource) res).getTagsAsString();
		((Button) findViewById(R.id.refreshFolder)).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					updateFile();
					returnToCaller(null);
				} catch (JSONException e) {
					showErrorDialog("JSON ERROR", "A JSON parsing error occured");
				} catch (SystemErrorException e) {
					showErrorDialog("System ERROR", "A system error occured");
					e.printStackTrace();
				} catch (GssHttpException e) {
					if(e.getStatusCode()==409)
						showErrorDialog("Duplicate Folder Name", "A file with the same name already exists.");
					else if(e.getStatusCode()==405)
						showErrorDialog("No permission", "You dont have permissions to rename this file.");
					else
						showErrorDialog("Invalid response code", "An invalid response code was returned:"+e.getStatusCode());
				}
				// TODO Auto-generated method stub
				
			}
		});
		rebuildPermissionList();
		((Button) findViewById(R.id.newPermission)).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if(groupsResource==null){
					getGroupsOnlyTask().execute(getDroidApplication().getUserDetails().getApiPath()+getDroidApplication().getUserDetails().getUsername()+"/groups/");
				}
				else
					showAddDialog();
				
			}
		});
	}

	protected void updateFolder() throws JSONException, SystemErrorException, GssHttpException {
		FolderResource folder = (FolderResource) res;
		Set<PermissionHolder> perms = folder.getPermissions();
		JSONObject json = new JSONObject();
		if (!folder.getName().equals(((EditText) findViewById(R.id.textFolderName)).getText().toString()))
			json.put("name", ((EditText) findViewById(R.id.textFolderName)).getText());
		json.put("readForAll", folder.isReadForAll());
		JSONArray perma = new JSONArray();
		int i = 0;
		for (PermissionHolder p : perms) {
			JSONObject po = new JSONObject();
			if (p.getUser() != null)
				po.put("user", p.getUser());
			else if (p.getGroup() != null){
				po.put("group", p.getGroupName());
			}
			po.put("read", p.isRead());
			po.put("write", p.isWrite());
			po.put("modifyACL", p.isModifyACL());
			perma.put(i, po);
			i++;
		}
		
		json.put("permissions", perma);
		Log.d("PERM",json.toString());
		new GssHttpCommands(getDroidApplication().getUserDetails()).updateFolder(folder.getUri(), json.toString());

	}
	

	protected void updateFile() throws JSONException, SystemErrorException, GssHttpException {
		FileResource folder = (FileResource) res;
		Set<PermissionHolder> perms = folder.getPermissions();
		JSONObject json = new JSONObject();
		if (!folder.getName().equals(((EditText) findViewById(R.id.textFolderName)).getText().toString()))
			json.put("name", ((EditText) findViewById(R.id.textFolderName)).getText());
		json.put("readForAll", folder.isReadForAll());
		JSONArray perma = new JSONArray();
		int i = 0;
		for (PermissionHolder p : perms) {
			JSONObject po = new JSONObject();
			if (p.getUser() != null)
				po.put("user", p.getUser());
			if (p.getGroup() != null){
				po.put("group", p.getGroupName());
			}
			po.put("read", p.isRead());
			po.put("write", p.isWrite());
			po.put("modifyACL", p.isModifyACL());
			perma.put(i, po);
			i++;
		}
		JSONArray taga = new JSONArray();
		i = 0;
		String tags = ((EditText) findViewById(R.id.textTags)).getText().toString().trim();
		if (!tags.equals(initialTagText)) {
			String[] tagset = tags.split(",");
			for (String t : tagset) {
				taga.put(i, t.trim());
				i++;
			}
			json.put("tags", taga);
		}
		json.put("permissions", perma);
		Log.d("PERM",json.toString());
		new GssHttpCommands(getDroidApplication().getUserDetails()).updateFile(folder.getUri(), json.toString());

	}

	RestResource getRestResource() {
		return res;
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)  {
	    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
	        onBackPressed();
	        return true;
	    }

	    return super.onKeyDown(keyCode, event);
	}
	
	public void onBackPressed() {
		// TODO Auto-generated method stub
		setResult(RESULT_CANCELED);
		// equivalent of 'return'
		finish();
		// super.onBackPressed();
	}

	public void returnToCaller(Bundle bundle) {
		// sets the result for the calling activity
		setResult(RESULT_OK);
		// equivalent of 'return'
		finish();
	}

	protected void showErrorDialog(String title, String message) {
		AlertDialog alertDialogn = new AlertDialog.Builder(this).create();
		alertDialogn.setTitle(title);
		alertDialogn.setMessage(message);
		alertDialogn.setButton("Continue", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		alertDialogn.setCancelable(true);
		alertDialogn.show();
	}

	protected GssAsyncTask getFolderTask() {
		GssAsyncTask getFolderTask = new GssAsyncTask(getDroidApplication().getUserDetails()) {
			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				myprogress = ProgressDialog.show(GssProperties.this, "Fetching Data", "Please Wait", true, false);
			}

			@Override
			protected RestResource doExecution(String[] params) throws Exception {
				return new GssHttpCommands(getDroidApplication().getUserDetails()).getFolderResource(params[0]);
			}

			@Override
			protected void onPostExecute(TaskResult result) {
				myprogress.hide();
				if (result.getResource() != null) {
					res = result.getResource();
					setContentView(R.layout.properties);
					createFolderLayout();
				} else if (result.getException() != null)
					handleRestException("TRASH", result.getException());
				super.onPostExecute(result);
			}

		};
		return getFolderTask;
	}

	protected GssAsyncTask getFileTask() {
		GssAsyncTask getFolderTask = new GssAsyncTask(getDroidApplication().getUserDetails()) {
			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				myprogress = ProgressDialog.show(GssProperties.this, "Fetching Data", "Please Wait", true, false);
			}

			@Override
			protected RestResource doExecution(String[] params) throws Exception {
				return new GssHttpCommands(getDroidApplication().getUserDetails()).getFileResource(params[0]);
			}

			@Override
			protected void onPostExecute(TaskResult result) {
				myprogress.hide();
				if (result.getResource() != null) {
					res = result.getResource();
					setContentView(R.layout.propertiesfile);
					createFileLayout();
				} else if (result.getException() != null)
					handleRestException("TRASH", result.getException());
				super.onPostExecute(result);
			}

		};
		return getFolderTask;
	}

	protected void handleRestException(String type, Throwable e) {
		String errorMessage = "";
		if (e instanceof SystemErrorException)
			errorMessage = e.getMessage();
		else if (e instanceof GssHttpException)
			if (((GssHttpException) e).getStatusCode() > 0)
				errorMessage = "Status Code:" + ((GssHttpException) e).getStatusCode() + "\n" + e.getMessage();
		AlertDialog alertDialogn = new AlertDialog.Builder(this).create();
		alertDialogn.setTitle("An error occured");
		alertDialogn.setMessage(errorMessage);
		alertDialogn.setButton("Continue", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		alertDialogn.setCancelable(true);
		alertDialogn.show();

	}
	
	private GssAsyncTask getGroupsTask() {
		GssAsyncTask getTrashTask = new GssAsyncTask(getDroidApplication().getUserDetails()) {
			@Override
			protected void onPreExecute() {
				// TODO Auto-generated method stub
				super.onPreExecute();
				myprogress = ProgressDialog.show(GssProperties.this, "Fetching Data", "Please Wait", true, false);
			}

			@Override
			protected RestResource doExecution(String[] params) throws Exception {
				GssHttpCommands http = new GssHttpCommands(getDroidApplication().getUserDetails());
				GroupsResource groups = http.getGroupsResource(params[0]);
				for(String pg : groups.getGroupPaths()){
					GroupResource g = http.getGroupResource(pg);
					for(String pu : g.getUserPaths()){
						GroupUserResource u = http.getGroupUserResource(pu);
						g.getUsers().add(u);
					}
					groups.getGroups().add(g);
				}
				return groups;
			}

			@Override
			protected void onPostExecute(TaskResult result) {
				myprogress.hide();
				if (result.getResource() != null){
					groupsResource=(GroupsResource) result.getResource();
					showAddDialog();
				}
				else if(result.getException()!=null){}
					//handleRestException("TRASH",result.getException());
				super.onPostExecute(result);
			}
		};
		return getTrashTask;
	}
	
	private GssAsyncTask getGroupsOnlyTask() {
		GssAsyncTask getTrashTask = new GssAsyncTask(getDroidApplication().getUserDetails()) {
			@Override
			protected void onPreExecute() {
				// TODO Auto-generated method stub
				super.onPreExecute();
				myprogress = ProgressDialog.show(GssProperties.this, "Fetching Data", "Please Wait", true, false);
			}

			@Override
			protected RestResource doExecution(String[] params) throws Exception {
				GssHttpCommands http = new GssHttpCommands(getDroidApplication().getUserDetails());
				GroupsResource groups = http.getGroupsResource(params[0]);
				
				return groups;
			}

			@Override
			protected void onPostExecute(TaskResult result) {
				myprogress.hide();
				if (result.getResource() != null){
					groupsResource=(GroupsResource) result.getResource();
					showAddDialog();
				}
				else if(result.getException()!=null){
					Log.e("ERR:","",result.getException());
					handleRestException("TRASH",result.getException());
				}
				super.onPostExecute(result);
			}
		};
		return getTrashTask;
	}
	
	private void showAddDialog(){
		final CharSequence[] items = {"Add User", "Add Group"};

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("Pick a color");
		builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
		    public void onClick(DialogInterface dialog, int item) {
		    	boolean user;
		       if(item ==0){
		    	   user=true;
		       }
		       else
		    	   user=false;
		       populateAddDialog(user);
		       dialog.dismiss();
		       
		    }
		});
		AlertDialog alert2 = builder.create();
		alert2.show();
		
	}
	
	private void populateAddDialog(final boolean user){
		final AlertDialog.Builder alert = new AlertDialog.Builder(GssProperties.this);
       	if(user){
       		alert.setTitle("Add User");
       		final AutoCompleteTextView input = new AutoCompleteTextView(GssProperties.this);
        	input.setTextColor(Color.BLACK);
    		input.setAdapter(new UserAdapter(GssProperties.this,getDroidApplication().getUserDetails(), getGroupNames(), user));
    		alert.setView(input);
    		
    		alert.setPositiveButton("Add", new DialogInterface.OnClickListener() {
    			public void onClick(DialogInterface dialog, int whichButton) {
    				String value = input.getText().toString().trim();
    				PermissionHolder holder = new PermissionHolder();
    				if(user)
    					holder.setUser(value);
    				else{
    					holder.setGroup(value);
    				}
    				if(res instanceof FolderResource)
    					((FolderResource)res).getPermissions().add(holder);
    				else
    					((FileResource)res).getPermissions().add(holder);
    				rebuildPermissionList();
    				
    			}
    		});

    		alert.setNegativeButton("Cancel",
    				new DialogInterface.OnClickListener() {
    					public void onClick(DialogInterface dialog, int whichButton) {
    						dialog.cancel();
    					
    					}
    				});
    		alert.show();
       	}
       	else{
       		AlertDialog.Builder builder = new AlertDialog.Builder(this);
    		builder.setTitle("Add Group");
    		builder.setSingleChoiceItems(getGroupNames().toArray(new String[0]), -1, new DialogInterface.OnClickListener() {
    		    public void onClick(DialogInterface dialog, int item) {
    		    	GroupResource selected = groupsResource.getGroups().get(item);    
    		    	PermissionHolder holder = new PermissionHolder();
    				holder.setGroup(selected.getName());
    				if(res instanceof FolderResource)
    					((FolderResource)res).getPermissions().add(holder);
    				else
    					((FileResource)res).getPermissions().add(holder);
    				rebuildPermissionList();
    		       dialog.dismiss();
    		       
    		    }
    		});
    		AlertDialog alert2 = builder.create();
    		alert2.show();
       	}
    	
	}
	
	public List<String> getGroupNames(){
		List<String> result = new ArrayList<String>();
		for(GroupResource g : groupsResource.getGroups()){
			result.add(g.getName());
		}
		return result;
	}
	
	private void rebuildPermissionList(){
		LayoutInflater layoutInflater = LayoutInflater.from(GssProperties.this);
		final LinearLayout properties = (LinearLayout) findViewById(R.id.propertiesList);
		if(properties.getChildCount()>0)
			properties.removeViews(0,properties.getChildCount());
		properties.removeAllViews();
		Iterator<PermissionHolder> it;
		if(res instanceof FolderResource)
			it= ((FolderResource) res).getPermissions().iterator();
		else
			it= ((FileResource) res).getPermissions().iterator();
		int i = 0;
		while (it.hasNext()) {
			final PermissionHolder perm = it.next();
			final View v = layoutInflater.inflate(R.layout.propertiesrow, null);
			populatePermissionList(perm, v, properties, i);
			i++;
		}
	}
	
	private void populatePermissionList(final PermissionHolder perm, final View v, final LinearLayout properties, int i){
		
		
		properties.addView(v, i);
		String owner = (perm.getUser() != null ? perm.getUser() : perm.getGroupName());
		
		if (res instanceof FolderResource && ((FolderResource) res).getOwner().equals(owner)) {
			((CheckBox) v.findViewById(R.id.read)).setEnabled(false);
			((CheckBox) v.findViewById(R.id.write)).setEnabled(false);
			((CheckBox) v.findViewById(R.id.acl)).setEnabled(false);
			((Button) v.findViewById(R.id.remove)).setVisibility(View.GONE);
		}
		else if (res instanceof FileResource && ((FileResource) res).getOwner().equals(owner)) {
			((CheckBox) v.findViewById(R.id.read)).setEnabled(false);
			((CheckBox) v.findViewById(R.id.write)).setEnabled(false);
			((CheckBox) v.findViewById(R.id.acl)).setEnabled(false);
			((Button) v.findViewById(R.id.remove)).setVisibility(View.GONE);
		}
		((TextView) v.findViewById(R.id.ownerName)).setText(owner);
		((CheckBox) v.findViewById(R.id.read)).setChecked(perm.isRead());
		((CheckBox) v.findViewById(R.id.write)).setChecked(perm.isWrite());
		((CheckBox) v.findViewById(R.id.acl)).setChecked(perm.isModifyACL());
		((CheckBox) v.findViewById(R.id.read)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				perm.setRead(isChecked);

			}
		});
		((CheckBox) v.findViewById(R.id.write)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				perm.setWrite(isChecked);

			}
		});
		((CheckBox) v.findViewById(R.id.acl)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				perm.setModifyACL(isChecked);

			}
		});
		((Button) v.findViewById(R.id.remove)).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v1) {
				properties.removeView(v);
				if(res instanceof FolderResource)
					((FolderResource) res).getPermissions().remove(perm);
				else
					((FileResource) res).getPermissions().remove(perm);

			}
		});
	}
	
	public GssDroidApplication getDroidApplication(){
		return (GssDroidApplication) getApplicationContext();
	}
}
